package com.wtwd.device.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.wtwd.common.base.model.Result;
import com.wtwd.common.sendemail.properties.BaseEmailProperties;
import com.wtwd.common.sendemail.service.SendEmailService;
import com.wtwd.common.sendsms.service.SmsService;
import com.wtwd.device.constant.*;
import com.wtwd.device.dao.AppUserMapper;
import com.wtwd.device.model.dto.AppConfigurationDTO;
import com.wtwd.device.model.dto.EmailConfiguration;
import com.wtwd.device.model.dto.LocalAppDTO;
import com.wtwd.device.model.dto.SMSConfiguration;
import com.wtwd.device.model.entity.AppUser;
import com.wtwd.device.model.entity.HfitAppUser;
import com.wtwd.device.model.vo.ResultVO;
import com.wtwd.device.service.*;
import com.wtwd.device.util.JWTUtil;
import com.wtwd.device.util.StringUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zdl
 * @since 2021-08-04
 */
@Service
public class AppUserServiceImpl implements AppUserService {

    private static final ThreadLocal<LocalAppDTO> LOCAL_APP = new ThreadLocal<>();

    @Resource
    private AppUserMapper appUserMapper;

    @Resource
    private MedalService medalService;

    @Resource
    private AppUserTargetService appUserTargetService;

    @Resource
    private AppUserTotalService appUserTotalService;

    @Resource
    private SmsService smsService;

    @Value("${sms.signname}")
    private String signname;

    @Resource
    private SendEmailService sendEmailService;

    @Resource
    private RedisService redisService;

    @Resource
    private AppConfigurationService appConfigurationService;


    @Override
    public boolean save(AppUser user) {
        return appUserMapper.insert(user) == 1;
    }

    @Override
    public boolean updateById(AppUser user) {
        return appUserMapper.updateById(user) == 1;
    }


    @Override
    public AppUser getUserByPhone(String phone) {
        return new LambdaQueryChainWrapper<>(appUserMapper)
                .eq(AppUser::getPhone, phone)
                .one();
    }

    @Override
    public AppUser getUserByEmail(String email) {
        return new LambdaQueryChainWrapper<>(appUserMapper)
                .eq(AppUser::getEmail, email)
                .one();
    }

    @Override
    public boolean updateByAppDeviceId(AppUser user) {
        //绑定注册账号
        AppUser userByAppDeviceId = getUserByAppDeviceId(user.getAppDeviceId());
        if (userByAppDeviceId != null) {
            user.setUserId(userByAppDeviceId.getUserId());
            return updateById(user);

        }
        return false;
    }

    @Override
    public AppUser getUserByAccountAndPwd(String account, String password) {
        boolean notEmail = StringUtil.isNotEmail(account);
        return new LambdaQueryChainWrapper<>(appUserMapper)
                .eq(!notEmail, AppUser::getEmail, account)
                .eq(notEmail, AppUser::getPhone, account)
                .eq(AppUser::getPassword, password)
                .one();
    }

    @Override
    public AppUser getUserByAppDeviceId(String appDeviceId) {
        return new LambdaQueryChainWrapper<>(appUserMapper)
                .eq(AppUser::getAppDeviceId, appDeviceId)
                .one();
    }

    /**
     * 去掉首位0
     *
     * @param phone
     * @return 正常的手机格式
     */
    private String getNormalPhone(String phone) {
        return Long.valueOf(phone).toString();
    }


    /**
     * 1.得到正常的手机号
     * 2.检查是否已发送
     * 是：查看发送状态,发送失败在次发送
     * 3.检查发送方式
     * 4.获取发送模板
     * 成功返回code
     *
     * @param phone
     * @param authType
     */

    @Override
    public ResultVO sendSMSAuthCode(String areaCode, String phone, Integer authType) {
        String normalPhone = getNormalPhone(phone);
        boolean isChina = MobileRegularExpEnum.isChina(areaCode);
        String moblie = isChina ? normalPhone : areaCode + normalPhone;
        if (redisService.hasKey(phone + SeparatorConstant.DELIMITER + authType)) {//已经发送
            Result result = smsService.querySMSLastStatus(moblie);
            if ("3".equals(result.getData())) {//发送成功
                return ResultVO.error(RespCode.AUTH_CODE_EXIST);
            }
        }
        boolean isExistAccount = getUserByPhone(phone) != null;
        switch (AuthCodeTypeEnum.getAuthCodeTypeEnum(authType)) {
            case MODIFY_PASSWORD:
                if (!isExistAccount) return ResultVO.error(RespCode.PHONE_NOT_EXIST);
                break;
            default:
                if (isExistAccount) return ResultVO.error(RespCode.PHONE_EXIST);
        }
        if (!MobileRegularExpEnum.checkAllMobileAreaCode(areaCode, phone)) {
            return ResultVO.error(RespCode.NONSUPPORT_PHONE);
        }
        SMSConfiguration smsConfiguration = appConfigurationService.getSMSConfigurationByAppId(getLocalApp().getAppId());
        String smsTemp = isChina ? smsConfiguration.getTemplateByLangAndType(LangEnum.ZH.name(), String.valueOf(authType))
                : smsConfiguration.getTemplateByLangAndType(LangEnum.EN.name(), String.valueOf(authType));
        Result result = smsService.sendSMSAuthCode(moblie, smsTemp, smsConfiguration.getSignature());
        return ResultVO.result(result.getData(), result.getCode(), result.getMsg());
    }


    @Override
    public ResultVO sendEmailAuthCode(String email, Integer authType) {
        if (redisService.hasKey(email + SeparatorConstant.DELIMITER + authType)) {//已经发送
            return ResultVO.error(RespCode.AUTH_CODE_EXIST);
        }
        String code = String.format("%06d", new Random().nextInt(999999));
        HashMap<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("email", email);
        EmailConfiguration emailConfiguration = appConfigurationService.getEmailConfigurationByAppId(getLocalApp().getAppId());
        BaseEmailProperties baseEmailProperties = new BaseEmailProperties();
        baseEmailProperties.setFormUser(getLocalApp().getAppName());
        baseEmailProperties.setSubject("Verification Code");
        baseEmailProperties.setToUser(email);
        baseEmailProperties.setTemplate(emailConfiguration.getTemplateByLangAndType(LangEnum.ZH.name(), String.valueOf(authType)));
        baseEmailProperties.setTemplateParams(params);
        baseEmailProperties.setImageNames(emailConfiguration.getImageNames());
        sendEmailService.send(baseEmailProperties);
        return ResultVO.success(code);

    }

    @Override
    public Long getCurrentUserId() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(Constant.HEADER_TOKEN_KEY);
        if (StringUtil.isNotEmpty(token)) {
            return JWTUtil.getUserId(token);
        }
        return null;
    }

    @Override
    public boolean deleteByAccount(String account, Integer accountType) {
        LambdaQueryWrapper<AppUser> queryWrapper = new LambdaQueryWrapper<>();

        if (UserTypeEnum.PHONE.getType() == accountType) {
            queryWrapper.eq(AppUser::getPhone, account);
        } else if (UserTypeEnum.EMAIL.getType() == accountType) {
            queryWrapper.eq(AppUser::getEmail, account);
        }
        return appUserMapper.delete(queryWrapper) == 1;
    }

    @Override
    public Map<String, Object> getUserInfoByUserId(Long friendId) {
        return appUserMapper.getUserInfoByUserId(friendId);
    }

    @Override
    public boolean isNotExistAccount(String account, Integer accountType) {
        AppUser user = null;
        if (UserTypeEnum.PHONE.getType() == accountType) {
            user = getUserByPhone(account);
        } else if (UserTypeEnum.EMAIL.getType() == accountType) {
            user = getUserByEmail(account);
        }
        return user == null ? true : false;
    }

    @Override
    public Map<String, Object> getUserInfoByHfitUserId(Long friendId) {
        return appUserMapper.getUserInfoByHfitUserId(friendId);
    }

    @Override
    public AppUser getUserByUserId(Long userId) {
        return appUserMapper.selectById(userId);
    }

    @Override
    public HfitAppUser getHfitUserByUserId(Long userId) {
        return appUserMapper.getHfitUserByUserId(userId);
    }

    @Override
    public boolean deleteById(Long id) {
        return appUserMapper.deleteById(id) == 1;
    }

    /**
     * 用户数据
     * 1.注册账号
     * 2.勋章
     * 3.用户目标
     * 4.用户总记录
     *
     * @param userId
     * @return
     */
    @Transactional
    @Override
    public boolean clearUserData(Long userId) {
        //deleteById(userId);
        medalService.deleteUserMedalByUserId(userId);
        appUserTargetService.deleteByUserId(userId);
        appUserTotalService.deleteByUserId(userId);
        return true;
    }

    @Override
    public void setLocalApp(Long appId) {
        AppConfigurationDTO configurationDTO = appConfigurationService.getById(appId);
        LocalAppDTO localAppDTO = new LocalAppDTO();
        localAppDTO.setAppId(configurationDTO.getId());
        localAppDTO.setAppName(configurationDTO.getName());
        localAppDTO.setUserTable(configurationDTO.getUserTable());
        LOCAL_APP.set(localAppDTO);
    }

    @Override
    public LocalAppDTO getLocalApp() {
        return LOCAL_APP.get();
    }
}
